package com.moarea.app.service.impl;

import com.moarea.app.lang.model.ResultObject;
import com.moarea.app.lang.utils.StringUtils;
import com.moarea.app.security.SecurityUtils;
import com.moarea.app.service.inter.IBaseService;
import com.moarea.app.util.PropertyUtil;
import com.sun.istack.internal.Nullable;
import org.apache.log4j.Logger;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import static com.moarea.app.resource.ResourceRepository.MD5_KEY;

/**
 * 基础service
 * 包括了一些公共方法的基础构建
 * <p>
 * jizhong
 * <p>
 * 2017-09-13
 */
public class BaseService implements IBaseService {

    //Log
    protected Logger logger = Logger.getLogger(BaseService.class);
    //system.properties
    protected static Properties properties = PropertyUtil.getReportConfig();

    /**
     * 检查传入参数的数据完整性
     * 主要是是否包含了时间戳 + 密文
     * 其他的业务参数可以在实现的时候进行检查
     * <p>
     * jizhong
     * <p>
     * 2017-09-13
     *
     * @param param 接口传入参数
     * @return 结果
     */
    @Override
    public ResultObject checkDataIntegrity(Map<String, Object> param) {

        if (StringUtils.isBlank(param, "TIME_STAMP")) {
            return ResultObject.createInstance(false, "时间戳不可为空");
        }

        if (StringUtils.isBlank(param, "CIPHER_TEXT")) {
            return ResultObject.createInstance(false, "密文不可为空");
        }

        return ResultObject.createInstance(true, "数据完整性校验通过");
    }

    /**
     * 安全性校验，用时间戳+MD5秘钥进行加密对比
     * <p>
     * jizhong
     * <p>
     * 2017-09-13
     *
     * @param timeStamp  时间戳
     * @param cipherText 密文
     * @return 是否通过验证
     */
    @Override
    public boolean checkAuthentication(String timeStamp, String cipherText) {
        return SecurityUtils.GetMd5(timeStamp.concat(MD5_KEY)).equals(cipherText);
    }


    /**
     * 业务处理前的基础数据校验方法
     * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param param  参数
     *               基础参数包括：
     *               TIME_STAMP 时间戳
     *               CIPHER_TEXT 密文
     * @param extras 额外需要验证的参数，这里使用可有选择的提供参数名
     * @return 结果
     */
    @Override
    public ResultObject validateCallParam(Map<String, Object> param, @Nullable Map<String, Object> extras) {

        //首先校验数据完整性
        ResultObject checkResult = checkDataIntegrity(param);

        if (!checkResult.isSuccess()) {
            return checkResult;
        }

        //数据完整性校验通过，则进一步检查加密
        boolean checkAuthenResult = checkAuthentication(param.get("TIME_STAMP").toString()
                , param.get("CIPHER_TEXT").toString());

        if (!checkAuthenResult)
            return ResultObject.createInstance(false, "未授权访问，请联系API提供商");

        //检查额外的参数
        if (extras != null && extras.size() > 0) {
            //验证额外参数
            checkResult = checkExtraParamCompleteness(param, extras);
            if (!checkResult.isSuccess()) {
                return checkResult;
            }
        }

        return ResultObject.createInstance(true, "基础数据校验通过");
    }

    /**
     * 重置Logger使用的对象
     *
     * @param clazz Class
     */
    @Override
    public void setLogger(Class clazz) {
        logger = Logger.getLogger(clazz);
    }


    /**
     * 针对MUI APP的参数完整性校验
     * <p>
     * 检查传入参数的数据完整性
     * 主要是是否包含了MD5_KEY
     * 其他的业务参数可以在实现的时候进行检查
     * <p>
     * jizhong
     * <p>
     * 2017-10-16
     *
     * @param param 接口传入参数
     * @return 结果
     */
    @Override
    public ResultObject checkDataIntegrityForMui(Map<String, Object> param) {


        if (StringUtils.isBlank(param, "MD5_KEY")) {
            return ResultObject.createInstance(false, "APP访问密钥不可以为空");
        }

        if (!param.get("MD5_KEY").toString().equals(MD5_KEY)) {
            return ResultObject.createInstance(false, "APP访问密钥不匹配");
        }

        return ResultObject.createInstance(true, "数据完整性校验通过");
    }


    /**
     * 针对MUI APP的参数完整性校验
     * <p>
     * 业务处理前的基础数据校验方法
     * <p>
     * jizhong
     * <p>
     * 2017-09-20
     *
     * @param param  参数
     *               MD5_KEY
     * @param extras 额外需检查参数
     * @return 结果
     */
    @Override
    public ResultObject validCallParamForMui(Map<String, Object> param, @Nullable Map<String, Object> extras) {

        //验证APP访问密钥
        ResultObject resultObject = checkDataIntegrityForMui(param);
        if (!resultObject.isSuccess()) {
            return resultObject;
        }

        if (extras != null && extras.size() > 0) {
            //验证额外参数
            resultObject = checkExtraParamCompleteness(param, extras);
            if (!resultObject.isSuccess()) {
                return resultObject;
            }
        }

        return ResultObject.createInstance(true, "数据完整性验证通过");
    }


    /**
     * 验证额外参数完整性
     *
     * @param extras 额外的参数
     * @param param  前端传如此参数
     * @return 解析结果
     */
    @Override
    public ResultObject checkExtraParamCompleteness(Map<String, Object> param, Map<String, Object> extras) {

        String[] extraArrays = new String[extras.size()];
        extras.keySet().toArray(extraArrays);

        List<String> extraList = Arrays.stream(extraArrays)
                .filter(item -> StringUtils.isBlank(param, item))
                .collect(Collectors.toList());
        if (extraList.size() > 0) {
            String returnStr = "参数：";
            for (int i = 0; i < extraList.size(); i++) {
                returnStr = returnStr.concat(i < extraList.size() - 1 ?
                        extras.get(extraList.get(i)).toString().concat(",") :
                        extras.get(extraList.get(i)).toString());
            }
            return ResultObject.createInstance(false, returnStr.concat("不可为空"));
        } else {
            return ResultObject.createInstance(true, "无额外参数");
        }

    }

}
